package com.yrmjhtdjxh.punch.util;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description: CIDR处理
 * @Author: russell
 * @Date: 2025/9/1
 */
public class SubnetUtil {
//    210.41.243.0/24
    private static final int EIGHT_BIT = 8;
    private static final int SEXTEEN_BIT = 16;
    private static final int TWENTY_FOR_BIT = 24;

    private static final int EIGHT_BIT_HEX = 0xFF;

    private static final int THIRTY_TWO_HEX = 0xFFFFFFFF;

    private final List<Integer> address = new ArrayList<>(); // ip address
    private final List<Integer> network = new ArrayList<>(); // 网段
    private final List<Integer> netmask = new ArrayList<>(); // 子网掩码

    public SubnetUtil() throws Exception {
        List<String> cidrs = loadCidrsFromFile();
        if (cidrs.isEmpty()) {
            cidrs.add("0.0.0.0/0");
        }

        int count = cidrs.size();
        for (int i = 0; i < count; i++) {
            String cidr = cidrs.get(i).trim();
            System.out.println(cidr);

            // 如果读到的是ip地址
            if (!cidr.contains("/")) {
                this.address.add(ipToInt(cidr));
                this.netmask.add(0xFFFFFFFF);
            } else {
            // 如果读到的是CIDR
                String[] parts = cidr.split("/");
                if (parts.length != 2) {
                    throw new IllegalArgumentException("Invalid CIDR notation: " + cidr);
                }
                int prefix;
                try {
                    prefix = Integer.parseInt(parts[1]);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("Invalid prefix in CIDR notation: " + parts[1]);
                }
                this.address.add(ipToInt(parts[0]));
                this.netmask.add(prefixToNetmaskInt(prefix));
            }
            this.network.add(address.get(i) & netmask.get(i));
        }

    }
    private List<String> loadCidrsFromFile() throws IOException {
        List<String> cidrs = new ArrayList<>();
        String temp;
        FileInputStream fis = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        try {
            fis = new FileInputStream("/usr/local/cidr.txt");
            isr = new InputStreamReader(fis);
            br = new BufferedReader(isr);
            temp = br.readLine();
            while (temp != null && !temp.trim().isEmpty()) {
                cidrs.add(temp);
                temp = br.readLine();
            }
        } finally {
            if (br != null) br.close();
            if (isr != null) isr.close();
            if (fis != null) fis.close();
        }
        return cidrs;
    }

    /**
     * @Description: 获得子网掩码
     * @param prefix
     * @return Integer
     */
    public Integer prefixToNetmaskInt(int prefix) {
        return prefix == 0 ? 0 : THIRTY_TWO_HEX << (32 - prefix);
    }

    public Integer ipToInt(String ipStr) {
        String[] octets = ipStr.split("\\.");
        if (octets.length != 4) {
            throw new IllegalArgumentException("Invalid IP address: " + address);
        }
        int ret = 0;
        for (int i = 0; i < octets.length; i++) {
            int octet = Integer.parseInt(octets[i]);
            if (octet < 0 || octet > 255) {
                throw new IllegalArgumentException("Octet out of range: " + octet);
            }
            ret |= octet << ((3 - i) * 8);
        }
        return ret;
    }

    public String intToIp(int ret) {
        return ((ret >> TWENTY_FOR_BIT) & EIGHT_BIT_HEX) + "." +
                ((ret >> SEXTEEN_BIT) & EIGHT_BIT_HEX) + "." +
                ((ret >> EIGHT_BIT) & EIGHT_BIT_HEX) + "." +
                (ret & EIGHT_BIT_HEX);
    }


    public SubnetInfo getSubnetInfo() {
        return new SubnetInfo();
    }

    public class SubnetInfo {
        /**
         * @Description: ip & netmask与 network = address & netmask 比较
         * @param ipStr
         * @return boolean
         */
        public boolean isInRange(String ipStr) {
            Integer ip = ipToInt(ipStr);
            boolean blog = false;
            for (int i = 0; i < network.size(); i++) {
                if ((ip & netmask.get(i)) == network.get(i)) {
                    blog = true;
                    break;
                }
            }
            return blog;
        }

        /**
         * @Description: 通过掩码中 1 的位数确定CIDR前缀长度
         * @return String
         */
        public String getCidr() {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < address.size(); i++) {
                String cidr = address.get(i) + "/" + Integer.bitCount(netmask.get(i));
                sb.append(cidr);
                if (i != address.size() - 1) {
                    sb.append(",");
                }
            }
            return sb.toString();
        }
    }
}
